﻿using StackExchange.Redis;
using System;
using System.Threading.Tasks;

namespace RedisDemo.Services
{
    public class LogService
    {
        private readonly RedisManager _redisManager;

        public LogService(RedisManager redisManager)
        {
            _redisManager = redisManager;
        }

        public async Task LogCommonAsync(string name, string message, LogLevel logLevel = LogLevel.info, int timeout = 5)
        {
            string key = $"common:{name}:{logLevel}";
            string startKey = $"{key}:start";

            var db = _redisManager.GetDatabase();

            var end = DateTime.Now.AddSeconds(timeout);
            while (DateTime.Now < end)
            {
                var hourStart = DateTime.Now.Hour;

                var lastHourStart = (int?)(await db.StringGetAsync(startKey));

                var tran = db.CreateTransaction();
                tran.AddCondition(Condition.StringEqual(startKey, lastHourStart));

                if (lastHourStart.HasValue && lastHourStart < hourStart)
                {
                    var t1 = tran.KeyRenameAsync(key, $"{key}:last");
                    var t2 = tran.KeyRenameAsync(startKey, $"{startKey}:pstart");

                    var t3 = tran.StringSetAsync(startKey, hourStart);
                }
                else if (!lastHourStart.HasValue)
                {
                    var t3 = tran.StringSetAsync(startKey, hourStart);
                }

                var t4 = tran.SortedSetIncrementAsync(key, message, 1);

                var t5 = LogRecentAsync(name, message, logLevel, tran);

                var result = await tran.ExecuteAsync();
                if (result)
                {
                    return;
                }

                await Task.Delay(TimeSpan.FromMilliseconds(100));
            }
        }

        public async Task LogRecentAsync(string name, string message, LogLevel logLevel = LogLevel.info, IBatch pipe = null)
        {
            string key = $"recent:{name}:{logLevel}";
            message = $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} {message}";

            pipe = pipe ?? _redisManager.GetDatabase().CreateBatch();
            var t1 = pipe.ListLeftPushAsync(key, message);
            var t2 = pipe.ListTrimAsync(key, 0, 99);

            if (!(pipe is ITransaction))
            {
                pipe.Execute();

                await Task.WhenAll(t1, t2);
            }
        }
    }

    public enum LogLevel
    {
        debug = 1,
        info = 2,
        warning = 3,
        error = 4,
        critical = 5
    }
}
